package core

import (
	"gitee.com/feimos/dm/utils"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"strings"
	"time"
)

const DmFile string = ".dm.yaml"
const DmIgnoreFile string = ".dmignore"
const DmBizarreExtname string = ".bizarre"

func LoadIgnoreFile(root string, doLog bool) []string {

	var ignoreList []string
	ignoreFile := utils.JoinPath(root, DmIgnoreFile)

	ignoreListBytes, err := ioutil.ReadFile(ignoreFile)

	if err == nil {
		if doLog {
			log.Printf("load ingore file at \"%v\"\n", ignoreFile)
		}
		contentSplit := strings.Split(string(ignoreListBytes), "\n")

		for _, item := range contentSplit {

			item = strings.TrimSpace(item)

			if strings.HasPrefix(item, "#") {
				continue
			}

			if len(item) > 0 {
				ignoreList = append(ignoreList, utils.JoinPath(root, item))
				if doLog {
					log.Printf("match ingore pattern as \"%v\"\n", item)
				}
			}

		}
	} else {
		// create DmIgnoreFile

		_, err := os.Create(ignoreFile)

		if err != nil {
			log.Fatalln(err)
		} else {
			content := "# 这是过滤配置文件\n*.ini\n"
			err := ioutil.WriteFile(ignoreFile, []byte(content), 0644)
			if err != nil {
				log.Fatalln(err)
			}
			log.Printf("create new ingore file at \"%v\"\n", ignoreFile)
		}
	}

	return ignoreList
}

type FileInfo struct {
	Size int64
	Name string
	Time time.Time
	Path string `yaml:"-"`
	Ext  string `yaml:"-"`
}

type FileMap = map[string][]*FileInfo

func CreateFileInfo(path string, info os.FileInfo) *FileInfo {
	ext := utils.GetExt(path)
	name := filepath.Base(path)

	if len(ext) == 0 || name == ext {
		ext = DmBizarreExtname
	}

	fileInfo := &FileInfo{
		Ext:  ext,
		Name: name,
		Path: path,
		Size: info.Size(),
		Time: info.ModTime(),
	}

	return fileInfo
}

func ScanRoot(root string, ignoreList []string, debug bool) (FileMap, error) {
	var files []*FileInfo
	fileMaps := make(FileMap)

	err := filepath.Walk(root, func(path string, info os.FileInfo, err error) error {

		if !utils.MatchIgnore(path, ignoreList, debug) && !info.IsDir() && !utils.IsFileAtRoot(path, root, DmFile) && !utils.IsFileAtRoot(path, root, DmIgnoreFile) {

			fileInfo := CreateFileInfo(path, info)
			files = append(files, fileInfo)
		}
		return nil
	})

	var fileCount int64

	if err != nil {
		return nil, err
	}

	for _, fileInfo := range files {

		if _, ok := fileMaps[fileInfo.Ext]; !ok {
			fileMaps[fileInfo.Ext] = []*FileInfo{}
		}

		if debug {
			fileCount++
			log.Printf("find #%v file at \"%v\"\n", fileCount, fileInfo.Path)
		}

		fileMaps[fileInfo.Ext] = append(fileMaps[fileInfo.Ext], fileInfo)

	}

	return fileMaps, nil
}

func UnifyPath(path string) string {

	if len(path) == 0 {
		return path
	}

	if strings.Contains(path, "?") {
		if strings.Index(path, "?") != strings.LastIndex(path, "?") {
			log.Fatalf("the path of \"%v\" contains more than one replacing char \"?\"\n", path)
		}

		path = strings.ReplaceAll(path, "?", DmBizarreExtname)
	}

	return path

}
